/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package Parser;

import lowlevel.BasicBlock;
import lowlevel.Function;
import lowlevel.Operand;
import lowlevel.Operation;

/**
 *
 * @author maxmuhlenkamp
 */
public class IterationStatement extends Statement{
    Expression expr;
    Statement stmt;
    
    public IterationStatement(Expression expr, Statement stmt){
        this.expr = expr;
        this.stmt = stmt;
    }

    @Override
    void print(String indent) {
        CMinusParser.oFile.println(indent + "IterationStatement:");
        CMinusParser.oFile.println(indent + "  while");
        expr.print(indent + "    ");
        stmt.print(indent + "  ");
        
        CMinusParser.oFile.flush();
    }

    @Override
    void genLLCode(Function func) {
        BasicBlock whileBlock = new BasicBlock(func);
        BasicBlock postBlock = new BasicBlock(func);
        
        // evaluate condition statement
        expr.genLLCode(func);

        // generate branch operation and operands
        Operation branch = new Operation(Operation.OperationType.BEQ, func.getCurrBlock());
        Operand src0 = new Operand(Operand.OperandType.REGISTER, expr.getRegNum());
        Operand src1 = new Operand(Operand.OperandType.INTEGER, 0);
        Operand src2 = new Operand(Operand.OperandType.BLOCK, postBlock.getBlockNum());
        
        // add the branch operation
        branch.setSrcOperand(0, src0);
        branch.setSrcOperand(1, src1);
        branch.setSrcOperand(2, src2);
        func.getCurrBlock().appendOper(branch);
        
        // append while block and set it to current block
        func.appendToCurrentBlock(whileBlock);
        func.setCurrBlock(whileBlock);
        
        // gen code on body statement
        stmt.genLLCode(func);
        
        // re-evaluate the condition and branch if necessary
        expr.genLLCode(func);
        
        // setup branch
        Operation branchIterate = new Operation(Operation.OperationType.BNE, func.getCurrBlock());
        Operand sr0 = new Operand(Operand.OperandType.REGISTER, expr.getRegNum());
        Operand sr1 = new Operand(Operand.OperandType.INTEGER, 0);
        Operand sr2 = new Operand(Operand.OperandType.BLOCK, whileBlock.getBlockNum());
        
        // add the branch operation
        branchIterate.setSrcOperand(0, sr0);
        branchIterate.setSrcOperand(1, sr1);
        branchIterate.setSrcOperand(2, sr2);
        func.getCurrBlock().appendOper(branchIterate);
        
        // append post block
        func.appendToCurrentBlock(postBlock);
        func.setCurrBlock(postBlock);
    }
}
